import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @ClassName: Ret
 * @Description: 高性能多参返回容器，支持按类型或索引获取值，提供流式操作
 * @Author: xcmrfc
 * @Date: 2025/06/05/09:06
 * @Version 2.0.0
 */
public final class Ret {
    private final Object[] values;                    // 使用数组存储，提高访问性能
    private final Map<Class<?>, int[]> typeIndexMap;  // 类型到索引的映射，避免重复存储对象
    private final int size;                           // 缓存大小，避免重复计算

    private Ret(Object[] values, Map<Class<?>, int[]> typeIndexMap) {
        this.values = values;
        this.typeIndexMap = typeIndexMap;
        this.size = values.length;
    }

    /**
     * 创建Ret实例
     *
     * @param args 参数列表
     * @return Ret实例
     */
    public static Ret create(Object... args) {
        if (args == null || args.length == 0) {
            throw new IllegalArgumentException("参数不能为空");
        }

        // 使用数组直接存储，避免ArrayList的装箱开销
        Object[] values = new Object[args.length];
        Map<Class<?>, List<Integer>> tempTypeMap = new HashMap<>();

        for (int i = 0; i < args.length; i++) {
            Object arg = args[i];
            values[i] = arg;

            if (arg != null) {
                tempTypeMap.computeIfAbsent(arg.getClass(), k -> new ArrayList<>()).add(i);
            }
        }

        // 转换为索引数组，节省内存
        Map<Class<?>, int[]> typeIndexMap = new HashMap<>();
        for (Map.Entry<Class<?>, List<Integer>> entry : tempTypeMap.entrySet()) {
            List<Integer> indices = entry.getValue();
            int[] indexArray = new int[indices.size()];
            for (int i = 0; i < indices.size(); i++) {
                indexArray[i] = indices.get(i);
            }
            typeIndexMap.put(entry.getKey(), indexArray);
        }

        return new Ret(values, typeIndexMap);
    }

    /**
     * 按类型获取第一个匹配的值
     */
    public <T> Optional<T> get(Class<T> clazz) {
        int[] indices = typeIndexMap.get(clazz);
        if (indices != null && indices.length > 0) {
            @SuppressWarnings("unchecked")
            T result = (T) values[indices[0]];
            return Optional.of(result);
        }
        return Optional.empty();
    }

    /**
     * 按类型获取所有匹配的值
     */
    public <T> List<T> getAll(Class<T> clazz) {
        int[] indices = typeIndexMap.get(clazz);
        if (indices == null || indices.length == 0) {
            return Collections.emptyList();
        }

        List<T> result = new ArrayList<>(indices.length);
        for (int index : indices) {
            @SuppressWarnings("unchecked")
            T value = (T) values[index];
            result.add(value);
        }
        return Collections.unmodifiableList(result);
    }

    /**
     * 按下标获取值（带类型检查）
     */
    public <T> Optional<T> get(int index, Class<T> clazz) {
        if (index < 0 || index >= size) {
            return Optional.empty();
        }

        Object value = values[index];
        if (value != null && clazz.isInstance(value)) {
            return Optional.of(clazz.cast(value));
        }
        return Optional.empty();
    }

    /**
     * 按下标获取原始值
     */
    public Object getRaw(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("索引超出范围: " + index + ", 大小: " + size);
        }
        return values[index];
    }

    /**
     * 获取大小
     */
    public int size() {
        return size;
    }

    /**
     * 检查是否为空
     */
    public boolean isEmpty() {
        return size == 0;
    }

    /**
     * 检查是否包含指定类型的值
     */
    public boolean contains(Class<?> clazz) {
        return typeIndexMap.containsKey(clazz);
    }

    /**
     * 获取所有值的流
     */
    public Stream<Object> stream() {
        return Arrays.stream(values);
    }

    /**
     * 获取指定类型值的流
     */
    public <T> Stream<T> stream(Class<T> clazz) {
        int[] indices = typeIndexMap.get(clazz);
        if (indices == null || indices.length == 0) {
            return Stream.empty();
        }
        return Arrays.stream(indices).mapToObj(i -> clazz.cast(values[i]));
    }

    /**
     * 过滤并转换值
     */
    public <T> List<T> filterAndMap(Class<T> clazz, Predicate<T> predicate, Function<T, T> mapper) {
        return stream(clazz)
                .filter(predicate)
                .map(mapper)
                .collect(Collectors.toList());
    }

    /**
     * 获取所有类型
     */
    public Set<Class<?>> getTypes() {
        return Collections.unmodifiableSet(typeIndexMap.keySet());
    }

    /**
     * 转换为Map（类型到值的映射）
     */
    public Map<Class<?>, Object> toTypeMap() {
        Map<Class<?>, Object> result = new HashMap<>();
        for (Map.Entry<Class<?>, int[]> entry : typeIndexMap.entrySet()) {
            Class<?> clazz = entry.getKey();
            int[] indices = entry.getValue();
            if (indices.length > 0) {
                result.put(clazz, values[indices[0]]);
            }
        }
        return Collections.unmodifiableMap(result);
    }

    /**
     * 转换为List
     */
    public List<Object> toList() {
        return Collections.unmodifiableList(Arrays.asList(values));
    }

    /**
     * 转换为数组
     */
    public Object[] toArray() {
        return values.clone();
    }

    @Override
    public String toString() {
        return "Ret{" + Arrays.toString(values) + "}";
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Ret ret = (Ret) obj;
        return size == ret.size &&
                Arrays.equals(values, ret.values) &&
                Objects.equals(typeIndexMap, ret.typeIndexMap);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(typeIndexMap, size);
        result = 31 * result + Arrays.hashCode(values);
        return result;
    }
}